package com.java.jvalidator.framework.validator;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.java.jvalidator.framework.TypeUtil;
import com.java.jvalidator.framework.ValidationException;
import com.java.jvalidator.framework.ValidationExceptionMsg;
import com.java.jvalidator.framework.XMLConfigConst;
import com.java.jvalidator.framework.config.Parameters;

public abstract class AbstractValidator implements Validator {
	private static final String EMPTY_PATTERN = "^$";
	protected Object target;
	protected String propertyName;

	public final boolean validate(Object target, String propertyName, Parameters param) throws ValidationException {
		if ((target == null) || (propertyName == null)) {
			throw new ValidationException(ValidationExceptionMsg.VALIDATION_ERROR);
		}

		this.target = target;
		this.propertyName = propertyName;

		if (conditionOk(target, param)) {
			return beginValidate(target, propertyName, param);
		}

		return true;
	}

	private boolean conditionOk(Object target, Parameters param) throws ValidationException {
		if (param == null) {
			return true;
		}
		String conditionProperty = param.getParameterValueAsString(XMLConfigConst.CONDITION_PROPERTY);

		if (TypeUtil.isStringNullOrEmpty(conditionProperty)) {
			return true;
		}
		String conditionValue = param.getParameterValueAsString(XMLConfigConst.CONDITION_VALUE);
		String[] properties = conditionProperty.split(XMLConfigConst.COMMA);
		String[] values = conditionValue.split(XMLConfigConst.COMMA);

		return comparePropertyAndValue(properties, values, target);
	}

	private boolean comparePropertyAndValue(String[] properties, String[] values, Object target) throws ValidationException {
		if (properties.length != values.length) {
			throw new ValidationException(ValidationExceptionMsg.VALIDATION_ERROR);
		}

		for (int i = 0; i < properties.length; i++) {
			String conditionPropertyName = properties[i];
			String conditionPropertyPattern = values[i];
			Object conditionPropertyValue = TypeUtil.getPropertyValue(target, conditionPropertyName);

			if (conditionPropertyValue == null) {
				return EMPTY_PATTERN.equals(conditionPropertyPattern);
			}

			Pattern p = Pattern.compile(conditionPropertyPattern, 32);
			Matcher matcher = p.matcher(conditionPropertyValue.toString());
			if (!matcher.matches()) {
				return false;
			}
		}
		return true;
	}

	// 同包的范围内可访问
	boolean compareResult(String conditionComparison, int compare) {
		if (compare < 0) {
			if (!XMLConfigConst.LESS_EQUAL.equalsIgnoreCase(conditionComparison)) {
				if (!XMLConfigConst.LESS_THAN.equalsIgnoreCase(conditionComparison)) {
					if (!XMLConfigConst.NOT_EQUAL.equalsIgnoreCase(conditionComparison))
						return false;
				}
			}
			return true;
		}
		if (compare > 0) {
			if (!XMLConfigConst.GREATER_EQUAL.equalsIgnoreCase(conditionComparison)) {
				if (!XMLConfigConst.GREATER_THAN.equalsIgnoreCase(conditionComparison)) {
					if (!XMLConfigConst.NOT_EQUAL.equalsIgnoreCase(conditionComparison))
						return false;
				}
			}
			return true;
		}
		if (!XMLConfigConst.EQUAL.equalsIgnoreCase(conditionComparison)) {
			if (!XMLConfigConst.GREATER_EQUAL.equalsIgnoreCase(conditionComparison)) {
				if (!XMLConfigConst.LESS_EQUAL.equalsIgnoreCase(conditionComparison))
					return false;
			}
		}
		return true;
	}

	protected abstract boolean beginValidate(Object paramObject, String paramString, Parameters paramParameters) throws ValidationException;
}
